package com.cndw.kungfu.model.goods;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.cndw.kungfu.config.ConstantsConfig;
import com.cndw.kungfu.config.ConstantsSystem;
import com.cndw.kungfu.dao.GoodsDao;
import com.cndw.kungfu.dao.GoodsModeDao;
import com.cndw.kungfu.domain.Goods;
import com.cndw.kungfu.domain.GoodsExt;
import com.cndw.kungfu.domain.GoodsMode;
import com.cndw.kungfu.domain.GoodsSuite;
import com.cndw.kungfu.domain.GoodsType;
import com.cndw.kungfu.ext.ContainerProcesser;
import com.cndw.kungfu.ext.LogUtil;
import com.cndw.kungfu.ext.TimeProcesser;
import com.cndw.kungfu.model.Context;
import com.cndw.kungfu.vo.goodsvo.GoodsVO;

@Component
public class GoodsManager {

	@Autowired
	private GoodsDao dao;
	@Autowired
	private GoodsModeDao mDao;

	private static Map<Integer, List<GoodsVO>> shopGoodIdsMap;

	private synchronized void initShopGoodIdsMap() {
		if (shopGoodIdsMap != null) {
			return;
		}
		shopGoodIdsMap = new HashMap<Integer, List<GoodsVO>>();
		LinkedHashSet<Integer> allIds = Context.getCacheCenter().getShopGoodsMap();

		Set<Integer> ids = new HashSet<Integer>();
		ContainerProcesser.setAdd(ids, ConstantsConfig.getShopHotIds());
		// ContainerProcesser.setAdd(ids, ConstantsConfig.getShopNewIds());

		LinkedList<GoodsVO> commShopList = new LinkedList<GoodsVO>();
		LinkedList<GoodsVO> leftShopList = new LinkedList<GoodsVO>();

		shopGoodIdsMap.put(0, commShopList);
		shopGoodIdsMap.put(-1, leftShopList);
		for (Integer goodsId : allIds) {
			GoodsMode mode = Context.getGoodsServer().getModeById(goodsId);
			if (mode.isOpenOnShop() == false) {// 没开放的跳过
				continue;
			}
			GoodsVO goodsVO = mode.toGoodsVO();
			int goodTypeId = mode.getGoodTypeId();
			if (!shopGoodIdsMap.containsKey(goodTypeId)) {
				shopGoodIdsMap.put(goodTypeId, new LinkedList<GoodsVO>());
			}
			commShopList.add(goodsVO);
			if (ids.contains(goodsId)) {
				leftShopList.add(goodsVO);
			}
			shopGoodIdsMap.get(goodTypeId).add(goodsVO);

		}

	}

	public List<GoodsVO> getAllSaLeist(int goodtype) {
		if (shopGoodIdsMap == null) {
			initShopGoodIdsMap();
		}
		List<GoodsVO> result = shopGoodIdsMap.get(goodtype);
		return result;
	}

	public List<GoodsVO> getSaleList(int goodtype, int offset, int limit) {

		List<GoodsVO> result = getAllSaLeist(goodtype);

		if (result == null || offset > result.size()) {
			return null;
		}

		int toIndex = limit + offset;

		if (toIndex > result.size()) {
			toIndex = result.size();
		}

		return result.subList(offset, toIndex);

	}

	/**
	 * 新增玩家物品
	 * 
	 * @param playerId
	 *            玩家ID
	 * @param goodsId
	 *            物品ID
	 * @param alertNum
	 *            增加数量
	 * @return
	 */
	public void addGoods(long playerId, int goodsId, int alertNum, int binding) {
		PlayerBoxs playerBoxs = Context.getGoodsServer().getPlayerBoxs(playerId);
		if (playerBoxs == null) {
			return;
		}
		GoodsMode modeGoods = Context.getGoodsServer().getModeById(goodsId);
		if (modeGoods == null) {
			return;
		}
		if (binding == 0 && modeGoods.getBindType() == 1) {
			binding = 1;
		}

		for (Goods e : playerBoxs.getBoxsGoods()) {
			/**
			 * 只增加绑定的
			 */
			if (e.getGoodsId() == goodsId && !playerBoxs.isLocked(e.getStoragePlace()) && e.getBinding() == binding) {
				if (e.getStackNum() < modeGoods.getMaxStack()) {
					int canNum = modeGoods.getMaxStack() - e.getStackNum();
					int sendNum = canNum < alertNum ? canNum : alertNum;
					e.alertStackNum(sendNum);

					alertNum -= sendNum;
				}
				if (alertNum <= 0) {
					break;
				}
			}
		}

		while (alertNum > 0) {
			int addStackNum = alertNum >= modeGoods.getMaxStack() ? modeGoods.getMaxStack() : alertNum;
			Goods goods = newGoods(goodsId, 0, 0, false, addStackNum, binding);
			goods.setPlayerId(playerId);
			playerBoxs.add(goods);
			alertNum -= addStackNum;
		}
	}

	/**
	 * 增加一个装备
	 * 
	 * @param playerId
	 * @param goodsId
	 * @param level
	 */
	public void addEquip(long playerId, int goodsId, int num, boolean luck, int binding) {
		GoodsMode goodsMode = Context.getGoodsServer().getModeById(goodsId);
		if (goodsMode == null) {
			return;
		}
		PlayerBoxs playerBoxs = Context.getGoodsServer().getPlayerBoxs(playerId);

		while (num > 0) {
			num--;
			Goods goods = newGoods(goodsId, 0, 0, luck, 1, binding);
			goods.setPlayerId(playerId);
			playerBoxs.add(goods);
		}
	}

	private Goods newGoods(int goodsId, int level, int forgeLevel, boolean luck, int stackNum, int binding) {
		Goods goods = new Goods();
		goods.setGoodsId(goodsId);
		goods.setLevel(level);
		goods.setLuck(luck);
		goods.setForgeLevel(forgeLevel);
		goods.setSource(1);
		goods.setStackNum(stackNum);
		goods.setCreateTime(TimeProcesser.getUnixTime());
		goods.setBinding(binding);

		/**
		 * 拾取绑定
		 */
		if (goods.getGoodsMode().getBindType() == 1) {
			goods.setBinding(1);
		}

		setGoodsLevel(goods);

		return goods;
	}

	/**
	 * 设置装备等级
	 * 
	 * @param goods
	 */
	public void setGoodsLevel(Goods goods) {
		GoodsExt ext = Context.getCacheCenter().getGoodsExtByLevel(goods.getGoodsId(), goods.getLevel());
		if (ext != null) {
			goods.setHp(ext.getHp());
			goods.setMp(ext.getMp());
			goods.setAttack(ext.getAttack());
			goods.setDefense(ext.getDefense());
		}
	}

	/**
	 * 升级装备等级
	 */
	public void upgradeGoodsLevel(Goods goods) {
		setGoodsLevel(goods);
	}

	/**
	 * 从数据库拿出全部道具
	 * 
	 * @return
	 */
	public List<GoodsMode> getAllGoodsModeFromDb() {
		List<GoodsMode> goodsModes = mDao.getAllGoods();
		return goodsModes;
	}

	/**
	 * 从数据库获得我的道具
	 * 
	 * @param playerId
	 * @return
	 */
	public List<Goods> getGoosFromDb(long playerId) {
		try {
			return dao.getByPlayer(playerId);
		} catch (Exception e) {
			return null;
		}

	}

	public Goods selectOne(long uid, long id) {
		try {
			return dao.selectOne(uid, id);
		} catch (Exception e) {
			e.printStackTrace();

		}
		return null;
	}

	/**
	 * 从数据库获取武器扩展属性
	 * 
	 * @param goodsId
	 * @return
	 */
	public List<GoodsExt> getGoodsExtFromDb() {
		try {
			return mDao.getGoodsExts();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public List<GoodsType> getGoodsTypeFromDb() {
		return mDao.getGoodsType();
	}

	/**
	 * 从数据库初始化背包
	 * 
	 * @param playerId
	 * @param boxsGirds
	 * @param holdGrids
	 * @return
	 */
	public PlayerBoxs initBoxsFromDb(long playerId, int boxsGirds, int holdGrids) {
		List<Goods> goods = new ArrayList<Goods>();
		try {
			goods = dao.getByPlayer(playerId);
		} catch (Exception e) {
			e.printStackTrace();
		}
		PlayerBoxs playerBoxs = new PlayerBoxs(playerId, goods, boxsGirds, holdGrids);
		return playerBoxs;
	}

	public List<GoodsSuite> getAllGoodsSuiteFromDb() {
		try {
			return mDao.getAllGoodsSuite();
		} catch (Exception e) {
			return new ArrayList<GoodsSuite>();
		}
	}

	/**
	 * 同步到数据库
	 * 
	 * @param goods
	 */
	public boolean saveDB(Goods goods) {

		try {
			if (goods.getId() <= 0 && goods.getStackNum() <= 0) {// 未入库,已作废
				return true;
			}
			goods.setUpdateTime(System.currentTimeMillis());
			if (goods.getId() <= 0 && goods.getPlayerId() > 0) {// 未入库过
				goods.setId(dao.insert(goods).longValue());
				if (goods.getStackNum() <= 0) {// 插入的时候并发删除
					LogUtil.getMain().info("update concurrent " + goods.getId() + " p:"+goods.getPlayerId());
					goods.commitSync();
				}
			} else {
				if (goods.getId() == 0) {
					LogUtil.getMain().info("update fail by id err  " + goods.info());
				} else if (goods.getStackNum() <= 0) {
					dao.deleteById(goods.getPlayerId(), goods.getId());
					goods.setId(0);
					// goods.setPlayerId(0);0830注释删除对象不清理id,防止交易转让后问题
				} else {
					int b = dao.saveDB(goods);
					if (b == 0) {
						LogUtil.getMain().info("update fail " + goods.info());
					}
				}
			}
		} catch (Exception e) {
			ConstantsSystem.throwExceptionDB(e);
			return false;
		}
		return true;
	}
}
